/*
 * @author Ugo Colesanti
 * @author Silvia Santini
 * @version 1.0 (January 27, 2011)
 *
 * Acknowledgment: This code is based upon the implementation of CTP for TinyOS written by
 * Omprakash Gnawali, Philip Levis, Kyle Jamieson, and Rodrigo Fonseca.
 */

/*
 * Copyright (c) 2011 Sapienza University of Rome.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the
 *   distribution.
 * - Neither the name of the Sapienza University of Rome nor the names of
 *   its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL SAPIENZA 
 * UNIVERSITY OF ROME OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
/*
 * Copyright (c) 2011 ETH Zurich.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the
 *   distribution.
 * - Neither the name of ETH Zurich nor the names of
 *   its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ETH 
 * ZURICH OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#include "Ctp.h"
#include "CtpRoutingEngine.h"
#include "CtpForwardingEngine.h"
#include "LinkEstimator.h"
Define_Module(Ctp);


void Ctp::handleMessage(cMessage * msg){
	trace() <<"Message arrived" ;
	int msgKind = msg->getKind();
	if (disabled && msgKind != NODE_STARTUP) {
		delete msg;
		msg = NULL;	// safeguard
		return;
	}

	switch (msgKind) {
		case APPLICATION_PACKET:{
			/*
			 * If an application packet is sent by the ForwardingEngine it's a decapsulated packet
			 * that must be notified to the application module.
			 * Otherwise, the packet comes from the application module and must be sent to the
			 * forwarding engine.
			 */
			int senderID = msg->getSenderModuleId() ;

			if(senderID == getParentModule()->getSubmodule("CtpForwardingEngine")->getId()){
				// from Forwarding Engine to App layer
				trace() <<"App packet from CtpForwardingEngine, sending to App layer..." ;
				send(msg,"toCommunicationModule") ;
			}
			else{
				// from app layer to forwarding engine
				trace() <<"Application Packet from App layer, sending to CtpForwardingEngine..." ;
				send(msg,"toCtpForwardingEngine") ;
			}

			return;
		}
		case MAC_CONTROL_MESSAGE:{
			/*
			 * CC2420MacControlMessage are generated by the CC2420Mac layer to simulate sendDone signals.
			 * Since ForwardingEngine and LinkEstimator both rely on Dual Buffer module, all signals are
			 * notified to the Dual Buffer module.
			 */
			send(msg,"toDualBuffer") ;
			return;
		}
		case NETWORK_CONTROL_COMMAND:{
			opp_error("Unexpected in this implementation. Remove this check if some changes need to be made.") ;
			break;
		}
		case NETWORK_LAYER_PACKET:{
			/*
			 * Network layer packet may be sent from Dual Buffer to Mac layer or from Mac Layer to
			 * ForwardingEngine or LinkEstimator (dual buffer is skipped during reception).
			 */
			trace() <<"Network packet..." ;
			int senderID = msg->getSenderModuleId() ;

			if(senderID == getParentModule()->getSubmodule("DualBuffer")->getId()){
				trace() <<"From Dual Buffer, sending to MAC module..." ;
				send(msg,"toMacModule") ;
			}
			else{
				if(dynamic_cast<CtpData*>(msg) != NULL){
					trace() <<"CtpData Packet, sending to Forwarding Engine..." ;
					send(msg,"toCtpForwardingEngine") ;
				}
				else if(dynamic_cast<CtpLe*>(msg) != NULL){
					trace() <<"Link Estimator Packet, sending to LinkEstimator..." ;
					send(msg,"toLinkEstimator") ;
				}
				else opp_error("Unknown packet type") ;
			}
			return;
		}
		case NODE_STARTUP:{
			/*
			 * Castalia implementation: NODE_STARTUP message activates each layer.
			 * We set the disabled flag to false and call the StdControl_start
			 * command of each module of CTP
			 */
			disabled = false;
			cfe->command_StdControl_start() ;
			cre->command_StdControl_start() ;
			le->command_StdControl_start() ;

			// Forward the message to underlying layers...
			send(new cMessage("Network --> Mac startup message", NODE_STARTUP), "toMacModule");

			break;
		}
		case NETWORK_CONTROL_MESSAGE:{
			send(msg,"toCommunicationModule") ;
			return;
		}

		default:{
			stringstream error;
			error << "default - unkown packet type: "<<msgKind ;

			opp_error(error.str().c_str()) ;
			break;
		}
	}
	delete msg ;
};

void Ctp::initialize(){
	disabled = true ;
	cfe = check_and_cast<CtpForwardingEngine*>(getParentModule()->getSubmodule("CtpForwardingEngine")) ;
	cre = check_and_cast<CtpRoutingEngine*>(getParentModule()->getSubmodule("CtpRoutingEngine")) ;
	le = check_and_cast<LinkEstimator*>(getParentModule()->getSubmodule("LinkEstimator")) ;
};

void Ctp::finishSpecific(){};
